#include <stdlib.h>
#include <time.h>
#include "thread.h"
#include <stdio.h>
#include <assert.h>


void print_thread_list(thread_list * l)
{
	printf("-----------------------------\n");
	thread_list * temp = l;
	do
    {
    	int p=0;
	   	if(temp->thread!=NULL)
	   	{
    		p=(temp->thread)->id;
			printf("-->%d(%d)    context: %p        status : %d\n", temp->num, p, &temp->thread->t, temp->thread->status);
		}
		else
			printf("-->%d(%d)    context: %p\n", temp->num, p, &temp->thread->t);
		temp = temp->next;
    }while (temp != NULL);
    printf("-----------------------------\n");
}

thread_list* init_thread_list()
{
  thread_list *l=malloc(sizeof(thread_list));
  l->thread=NULL;
  l->next=NULL;
  l->num = 0;
  srand(time(NULL));

  return l;
}


void add_thread(thread_list *l, thread_t *t)
{
  //printf("on ajoute un thread\n");  
	thread_list * new_l=malloc(sizeof(thread_list));
	thread_list *tmp=l;
	while(tmp->next!=NULL)
	{
		tmp=tmp->next;
	}
	tmp->next = new_l;
	new_l->num=tmp->num+1;
	new_l->thread=t;
	new_l->next=NULL;
	//print_thread_list(list_thread);
}


thread_t* get_thread(thread_list *l)
{
  //fprintf(stderr,"debut de get_thread\n");
  thread_list *tmp=l;
  
  if(l->next==NULL)
    return NULL;
  //on redonne un numéro a tous les éléments de la liste
  int toto=0;
	while(tmp!=NULL)
	{
		//tmp->num = toto;
		//if(tmp->thread!=NULL)
		//	tmp->thread->id = toto;
		tmp=tmp->next;
		toto++;
	}

	if (toto <= 0){
		//fprintf(stderr,"toto vaut %d\n",toto);
		return NULL;
	}
  
  
  
  int res=(rand()%(toto));
  //if(res<0)return NULL;
  //fprintf(stderr,"res: %d / toto: %d\n",res,toto);
  
  thread_list * temp = l->next;

  int comp=1;
  for(comp=1;comp<res;comp++)
    {
      temp=temp->next;
    }
    //print_thread_list(list_thread);
  //if(temp!=NULL)
    //fprintf(stderr,"le num du thread retourne est %d\n",temp->num);
  	//print_thread_list(list_thread);
  	//printf("on fait un get_thread sur le thread %d\n",temp->num);
  return temp->thread;
}




/* NOTA BENE : pas de gestion d'erreur, le thread a supprimer doit exister! */
void remove_thread(thread_list * l, thread_t * flupke)
{
  thread_list* prev = l;
  thread_list * temp = l;
  assert(temp->thread!=flupke);

		while (temp->next != NULL)
		{
			prev = temp;
			temp = temp->next;
			if(temp->thread->id==flupke->id)
			{
			  prev->next = temp->next;
			  
			  VALGRIND_STACK_DEREGISTER(temp->thread->valgrind);
			  
			//ce free est nécessaire pour éviter les fuites mémoire mais entraine des segfault de temps en temps ! ?
			  //free(temp->thread->t.uc_stack.ss_sp);
			  
			  free(temp);
			  break;
			}
		}


}




